package ar.uade.distribuidas.tpo.cpe.dao;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.text.DateFormat;
import java.text.Normalizer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import ar.uade.distribuidas.tpo.base.dominiodto.*;
import ar.uade.distribuidas.tpo.base.remoto.IGestionRodamientos;
import ar.uade.distribuidas.tpo.base.utils.FormatUtils;


public class ListaPrecioXmlDAO {

	private static ListaPrecioXmlDAO instancia;
	private static String ARCHIVO = "lista-de-precios.xml";
	private Document doc;

	private ListaPrecioXmlDAO() {
		super();
	}

	private void createDocument(){
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
			doc = builder.parse(ARCHIVO);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public static ListaPrecioXmlDAO getInstancia() {
		if (instancia == null) {
			instancia = new ListaPrecioXmlDAO();
			instancia.createDocument();
		}
		return instancia;
	}

	public Set<ListaPrecioDTO> recuperarListaPrecio() {
		Set<ListaPrecioDTO> lps = new HashSet<ListaPrecioDTO>();
		NodeList nodos = doc.getElementsByTagName("ListaPrecios");
		for (int i = 0; i < nodos.getLength(); i++) {
			if (nodos.item(i).hasChildNodes()) {
				lps.add(mapStock((Element) nodos.item(i)));
			}
		}
		return lps;
	}

	private ListaPrecioDTO mapStock(Element eleListaP) {

		ListaPrecioDTO lp = new ListaPrecioDTO();
		Element auxElem;
		try {
			Element elemProv = (Element) eleListaP.getElementsByTagName("Cuil").item(0);
			//Proveedor prov = new Proveedor();
			
			Long cuil = ((Long.parseLong(elemProv.getTextContent())));
			//prov.setNombre(elemProv.getAttribute("RazonSocial")); No hace falta ya que sacamos el proveedor de la DB
			//ProveedorDTO pDTO = new GestionProveedor().getProveedor(cuil);
			ProveedorDTO pr = new ProveedorDTO(cuil);//new Proveedor(pDTO.getCuil(), pDTO.getNombre());
			lp.setProveedor(pr);

			elemProv = (Element) eleListaP.getElementsByTagName("Vigencia").item(0);
			auxElem = (Element) elemProv.getElementsByTagName("Fecha").item(0);
	
			DateFormat df = new SimpleDateFormat(FormatUtils.DATE_PATTERN);
			lp.setFechaDesde((df.parse(auxElem.getTextContent())));

			auxElem = (Element) elemProv.getElementsByTagName("Termino").item(0);
			
			
			Calendar calendar = Calendar.getInstance();
			
			
			calendar.setTime(lp.getFechaDesde()); // Configuramos
																			// la
																			// fecha
																			// que
																			// se
																			// recibe
			
			//String aux = auxElem.getTextContent();
			calendar.add(Calendar.DAY_OF_YEAR, Integer.valueOf(auxElem.getTextContent())); // numero
																									// de
																									// dias
																									// a
																									// aniadir,
																									// o
																									// restar
																									// en
																									// caso
																									// de
																									// dias<0

			lp.setFechaHasta(calendar.getTime());
			
			
			Element CDVelem = (Element) doc.getElementsByTagName("CondicionesDeVenta").item(0);
			NodeList nodosPoliticaDTOs = CDVelem.getChildNodes();
			CondicionDeVentaDTO condicion;
			List<CondicionDeVentaDTO> condiciones = new LinkedList<CondicionDeVentaDTO>();
			int iter = 0;
			while(iter<nodosPoliticaDTOs.getLength()){
				if(nodosPoliticaDTOs.item(iter).getNodeType() == Node.ELEMENT_NODE){ //Asumo que esta definido en el formato del
					Node nodo = (Node) nodosPoliticaDTOs.item(iter);					 //  XML que el primer elemento de "CondicionesDeVenta" es un medio de pago.
					auxElem = (Element) nodo;
					condicion = CondicionDeVentaXmlParser.parseCDV(auxElem);
					condiciones.add(condicion);
				}
				iter++;
			}
			lp.setCondicionesDeVenta(condiciones);
//			Object politica = null;
//			Class<?> clase = null;
//			List<PoliticaDTO> listaPoliticaDTOs = new LinkedList<PoliticaDTO>(); 
//			String path = "ar.uade.distribuidas.tpo.base.dominiodto.";
//			for(int b=iter; b<nodosPoliticaDTOs.getLength();b++){  //empiezo por el 2 porque el primero (el nro 1) es un medio de pago  
//				if(nodosPoliticaDTOs.item(b).getNodeType() == Node.ELEMENT_NODE){
//					auxElem = (Element) nodosPoliticaDTOs.item(b); 
//					try{
//						
//						clase = Class.forName(path + quitarTildes(auxElem.getTagName()+"DTO"));				 
//						NamedNodeMap atributosPolit = auxElem.getAttributes();
//						String valores="";
//						for (int c = 0; c < atributosPolit.getLength(); c++) { //itero la lista de atributos de la politica (Por ejemplo, dias para financiacion)
//						
//							            Attr attr = (Attr) atributosPolit.item(c);				    
//							            //String attrName = attr.getNodeName();					         
//							            String attrValue = attr.getNodeValue();
//							            if(valores.isEmpty())
//							            	valores = attrValue;							     
//							            else
//							            	valores = valores.concat(","+attrValue);
//						}
//						
//						if(auxElem.getElementsByTagName("Descuento").getLength() > 0){
//							valores.concat(",-"+auxElem.getElementsByTagName("Descuento").item(0).getTextContent());
//						}else if(auxElem.getElementsByTagName("Recargo").getLength() > 0){
//							valores = valores.concat( ","+auxElem.getElementsByTagName("Recargo").item(0).getTextContent());
//						}
//						
//						Constructor<?> cons = clase.getConstructor(String.class); 
//						politica = cons.newInstance(valores); 
//						listaPoliticaDTOs.add((PoliticaDTO) politica);
//						
//					}catch(ClassNotFoundException ce){
//						ce.printStackTrace();
//					
//					} catch (NoSuchMethodException e) {
//						e.printStackTrace();
//					} catch (SecurityException e) {
//						e.printStackTrace();
//					} catch (InstantiationException e) {					
//						e.printStackTrace();
//					} catch (IllegalAccessException e) {
//						e.printStackTrace();
//					} catch (IllegalArgumentException e) {
//						e.printStackTrace();
//					} catch (InvocationTargetException e) {
//						e.printStackTrace();
//					}
//				}
//			}
			// FIXME
//			condicionVenta.setPoliticas(listaPoliticaDTOs);
//		
//			
//			lp.setCondicionesDeVenta(condicionVenta);
			
			
			Element rodamientoElem = (Element) eleListaP.getElementsByTagName("Rodamientos").item(0);
			NodeList items = rodamientoElem.getElementsByTagName("Item");
				
			for (int j = 0; j < items.getLength(); j++) {
				Node item = items.item(j);

				if (item.getNodeType() == Node.ELEMENT_NODE) {
					Element it = (Element) item;
					RodamientoDTO rodDTO = new RodamientoDTO(Long.parseLong(it.getAttribute("serie")), getValue("Sufijo", it),
							getValue("Marca", it), getValue("Origen", it));
					
					IGestionRodamientos gestionRod = null;
					try {
						
						gestionRod = (IGestionRodamientos) Naming.lookup("GestionRodamientos");
						
						if(gestionRod.existeRodamiento(rodDTO)){
							ItemListaPrecioDTO ip = new ItemListaPrecioDTO();
							auxElem = (Element) it.getElementsByTagName("Precio").item(0);
							Double costo = Double.valueOf(auxElem.getTextContent());
							ip.setCosto(costo);
							ip.setRodamiento(rodDTO);
							lp.addItem(ip);
							
						}
						
					} catch (RemoteException e) {
						e.printStackTrace();
					} catch (MalformedURLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (NotBoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					
				}

			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return lp;
	}

	private static String getValue(String tag, Element element) {
		NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
		Node node = (Node) nodes.item(0);
		if (node != null) {
			return node.getNodeValue();
		}
		return "";
	}
	
	private String quitarTildes(String original){
		   String sinTildes = null;
		   //Normalizamos en la forma NFD (Canonical decomposition)
		   original = Normalizer.normalize(original, Normalizer.Form.NFD);
		   //Reemplaza los tildes usando una expresi�n regular de Bloque Unicode
		   sinTildes = original.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
		    
		   return sinTildes;
		}

}
